package city.spring.modules.material.controller;

import city.spring.modules.material.entity.MaterialQuantityEntity;
import city.spring.modules.material.entity.MaterialwarehousingEntity;
import city.spring.modules.material.entity.MaterialwarehousingMaterialExtEntity;
import city.spring.modules.material.repository.MaterialwarehousingMaterialExtRepository;
import city.spring.modules.material.service.MaterialQuantityService;
import city.spring.modules.material.service.MaterialSettingService;
import city.spring.modules.material.service.MaterialwarehousingMaterialExtService;
import city.spring.modules.material.service.MaterialwarehousingService;
import city.spring.modules.material.vo.MaterialwarehousingMaterialVO;
import city.spring.utils.MyBatisUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.api.ApiController;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import org.apache.commons.lang.StringUtils;
import org.springframework.data.domain.Pageable;
import org.springframework.data.web.PageableDefault;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * Controller：物资入库与货架关联
 *
 * @author 谢金婷
 * @date 2020-07-17 11:44:42
 */
@RestController
@RequestMapping("/materialwarehousing/{materialwarehousingId}/material")
public class MaterialwarehousingMaterialExtController extends ApiController {
    private final MaterialwarehousingMaterialExtService materialwarehousingMaterialExtService;
    private final MaterialwarehousingMaterialExtRepository warehousingMaterialExtRepository;
    private final MaterialQuantityService materialQuantityService;
    private final MaterialwarehousingService materialwarehousingService;
    private final MaterialSettingService materialSettingService;
    /**
     * 实体类可排序字段
     */
    private final List<SFunction<MaterialwarehousingMaterialExtEntity, ?>> entityOrderFields;

    public MaterialwarehousingMaterialExtController(MaterialwarehousingMaterialExtService materialwarehousingMaterialExtService, MaterialwarehousingMaterialExtRepository warehousingMaterialExtRepository, MaterialQuantityService materialQuantityService, MaterialwarehousingService materialwarehousingService, MaterialSettingService materialSettingService) {
        this.materialwarehousingMaterialExtService = materialwarehousingMaterialExtService;
        this.warehousingMaterialExtRepository = warehousingMaterialExtRepository;
        this.materialQuantityService = materialQuantityService;
        this.materialwarehousingService = materialwarehousingService;
        this.materialSettingService = materialSettingService;
        entityOrderFields = new ArrayList<>();
        entityOrderFields.add(MaterialwarehousingMaterialExtEntity::getId);
        entityOrderFields.add(MaterialwarehousingMaterialExtEntity::getMaterialwarehousingId);
        entityOrderFields.add(MaterialwarehousingMaterialExtEntity::getWarehousingquantity);
        entityOrderFields.add(MaterialwarehousingMaterialExtEntity::getTotal);
    }

    @ModelAttribute
    public void getMaterialwarehousingId(@PathVariable String materialwarehousingId) {
        if (materialwarehousingId == null) {
            throw new RuntimeException("入库单ID必须不为空");
        }
        System.out.println("materialwarehousingId" + materialwarehousingId);
    }


    /**
     * 获取全部的 <strong>物资入库与货架关联</strong> 列表
     */
    @GetMapping("all")
    public Object listAll(@PageableDefault Pageable pageable, MaterialwarehousingMaterialExtEntity entity) {
        LambdaQueryChainWrapper<MaterialwarehousingMaterialExtEntity> lambdaQuery = buildLambdaQuery(entity);
        MyBatisUtils.lambdaQueryAddOrder(lambdaQuery, pageable, entityOrderFields);
        return success(lambdaQuery.list());
    }

//    /**
//     * 分页获取 <strong>物资入库与货架关联</strong> 列表
//     *
//     * @param pageable 分页参数信息
//     */
//    @GetMapping
//    public Object list(@PageableDefault Pageable pageable, MaterialwarehousingShelfExtEntity entity) {
//        LambdaQueryChainWrapper<MaterialwarehousingShelfExtEntity> lambdaQuery = buildLambdaQuery(entity);
//        MyBatisUtils.lambdaQueryAddOrder(lambdaQuery, pageable, entityOrderFields);
//        Page<MaterialwarehousingShelfExtEntity> page = lambdaQuery.page(MyBatisUtils.toPage(pageable, false));
//        return success(page);
//    }

    /**
     * 获取物资出库所有货架列表
     *
     * @param materialwarehousingId
     * @return
     */
    @GetMapping
    public Object list(@PathVariable String materialwarehousingId) {
        return success(warehousingMaterialExtRepository.getWarehousingMaterials(materialwarehousingId));
    }

//    /**
//     * 获取一个 <strong>物资入库与货架关联</strong>
//     *
//     * @param id 主键ID
//     */
//    @GetMapping("{id}")
//    public Object info(@PathVariable String id) {
//        return success(materialwarehousingShelfExtService.getById(id));
//    }

    /**
     * @param materialwarehousingId
     * @param extId
     * @return
     */
    @GetMapping("{extId}")
    public Object getInfo(@PathVariable String materialwarehousingId, @PathVariable String extId) {
        return success(warehousingMaterialExtRepository.getWarehousingMaterial(materialwarehousingId, extId));
    }

//    /**
//     * 添加一个 <strong>物资入库与货架关联</strong>
//     *
//     * @param entity 修改后的信息
//     */
//    @PostMapping
//    public Object add(@RequestBody MaterialwarehousingShelfExtEntity entity) {
//        materialwarehousingShelfExtService.saveMaterialwarehousingShelfExt(entity);
//
//        HttpHeaders headers = new HttpHeaders();
//        headers.add(HttpHeaders.LOCATION, String.valueOf(entity.getId()));
//        return new ResponseEntity<>(headers, HttpStatus.CREATED);
//    }

    /**
     * 给入库单添加多个货架信息
     *
     * @param materialwarehousingId 入库单ID
     * @param materials             所添加的物资信息列表
     * @return
     */
    @PostMapping
    public Object addAll(@PathVariable String materialwarehousingId, @RequestBody List<MaterialwarehousingMaterialExtEntity> materials) {
        // 入库单信息
        MaterialwarehousingEntity materialwarehousingEntity = materialwarehousingService.getById(materialwarehousingId);
        // 查出已有的数据
        List<MaterialwarehousingMaterialVO> dbMaterials = warehousingMaterialExtRepository.getWarehousingMaterials(materialwarehousingId);

        // 数据库已经存在的物资列表
        Set<String> dbMaterialIdsSet = dbMaterials.stream()
                .map(MaterialwarehousingMaterialExtEntity::getMaterialId)
                .collect(Collectors.toSet());
        // 过滤掉已经存在数据库的数据
        List<MaterialwarehousingMaterialExtEntity> needSaveMaterials = materials.stream()
                .filter(item -> {
                    item.setMaterialwarehousingId(materialwarehousingId);
                    // 总价=数量*单价
                    item.setTotal(item.getWarehousingquantity().multiply(item.getUnitprice()));
                    item.setWarehouseId(materialwarehousingEntity.getWarehouseId());
                    item.setWarehousingdate(materialwarehousingEntity.getWarehousingdate());
                    item.setStorehouseId(materialwarehousingEntity.getStorehouseId());
                    item.setCancellation("已入库");
                    item.setRemainingQuantity(item.getWarehousingquantity());
                    String materialId = item.getMaterialId();
                    // 过滤出不存在数据库中的数据
                    return materialId != null && !dbMaterialIdsSet.contains(materialId);
                }).collect(Collectors.toList());

        if (!needSaveMaterials.isEmpty()) {
            materialwarehousingMaterialExtService.saveBatch(needSaveMaterials);
        }

        // 统计库存 单价平均加权计算
        for (MaterialwarehousingMaterialExtEntity material : needSaveMaterials) {
            // 根据物资id查找库存表是否有该物资
            MaterialQuantityEntity materialQuantityEntity = materialQuantityService.getByMaterialId(material.getMaterialId());
            // 如果为空 则新增库存表
            if (materialQuantityEntity == null) {
                MaterialQuantityEntity materialQuantityEntity1 = new MaterialQuantityEntity();
                materialQuantityEntity1.setCategoryId(material.getCategoryId());
                materialQuantityEntity1.setMaterialId(material.getMaterialId());
                materialQuantityEntity1.setCode(material.getCode());
                materialQuantityEntity1.setUnitmeasurement(material.getUnitmeasurement());
                materialQuantityEntity1.setUnitprice(material.getUnitprice());
                materialQuantityEntity1.setStorehouseId(material.getStorehouseId());
                materialQuantityEntity1.setWarehousingquantity(material.getWarehousingquantity());
                materialQuantityEntity1.setQuantity(material.getWarehousingquantity());
                materialQuantityEntity1.setTotal(material.getTotal());
                HttpHeaders headers = new HttpHeaders();
                headers.add(HttpHeaders.LOCATION, String.valueOf(materialQuantityEntity1.getId()));
                materialQuantityService.saveMaterialQuantity(materialQuantityEntity1);
                // 如果入库仓库与materialQuantityEntity仓库相同，则更新库存
            } else if (material.getStorehouseId().equals(materialQuantityEntity.getStorehouseId())) {
                // 更新库存
                BigDecimal quantity = materialQuantityEntity.getQuantity() == null ? BigDecimal.ZERO : materialQuantityEntity.getQuantity();
                BigDecimal warehousingquantity = materialQuantityEntity.getWarehousingquantity() == null ? BigDecimal.ZERO : materialQuantityEntity.getWarehousingquantity();
                BigDecimal total = materialQuantityEntity.getTotal() == null ? BigDecimal.ZERO : materialQuantityEntity.getTotal();

                materialQuantityEntity.setQuantity(quantity.add(material.getWarehousingquantity()));
                materialQuantityEntity.setWarehousingquantity(warehousingquantity.add(material.getWarehousingquantity()));
                materialQuantityEntity.setTotal(total.add(material.getTotal()));
                // 计算价格 = total/quantity
                materialQuantityEntity.setUnitprice(materialQuantityEntity.getTotal().divide(materialQuantityEntity.getQuantity(), 2));

                materialQuantityService.lambdaUpdate()
                        .set(MaterialQuantityEntity::getQuantity, materialQuantityEntity.getQuantity())
                        .set(MaterialQuantityEntity::getWarehousingquantity, materialQuantityEntity.getWarehousingquantity())
                        .set(MaterialQuantityEntity::getTotal, materialQuantityEntity.getTotal())
                        .set(MaterialQuantityEntity::getUnitprice, materialQuantityEntity.getUnitprice())
                        .eq(MaterialQuantityEntity::getId, materialQuantityEntity.getId())
                        .update();
            } else if (!material.getStorehouseId().equals(materialQuantityEntity.getStorehouseId())) {
                MaterialQuantityEntity materialQuantityEntity2 = materialQuantityService.getByMaterialIdAndStorehouseId(material.getMaterialId(), material.getStorehouseId());
                if (materialQuantityEntity2 != null) {
                    // 更新库存
                    BigDecimal quantity = materialQuantityEntity2.getQuantity() == null ? BigDecimal.ZERO : materialQuantityEntity2.getQuantity();
                    BigDecimal warehousingquantity = materialQuantityEntity2.getWarehousingquantity() == null ? BigDecimal.ZERO : materialQuantityEntity2.getWarehousingquantity();
                    BigDecimal total = materialQuantityEntity2.getTotal() == null ? BigDecimal.ZERO : materialQuantityEntity2.getTotal();

                    materialQuantityEntity2.setQuantity(quantity.add(material.getWarehousingquantity()));
                    materialQuantityEntity2.setWarehousingquantity(warehousingquantity.add(material.getWarehousingquantity()));
                    materialQuantityEntity2.setTotal(total.add(material.getTotal()));
                    // 计算平均单价 = total/quantity
                    materialQuantityEntity2.setUnitprice(materialQuantityEntity2.getTotal().divide(materialQuantityEntity2.getQuantity(), 2));

                    materialQuantityService.lambdaUpdate()
                            .set(MaterialQuantityEntity::getQuantity, materialQuantityEntity2.getQuantity())
                            .set(MaterialQuantityEntity::getWarehousingquantity, materialQuantityEntity2.getWarehousingquantity())
                            .set(MaterialQuantityEntity::getTotal, materialQuantityEntity2.getTotal())
                            .set(MaterialQuantityEntity::getUnitprice, materialQuantityEntity2.getUnitprice())
                            .eq(MaterialQuantityEntity::getId, materialQuantityEntity2.getId())
                            .update();
                } else {
                    MaterialQuantityEntity materialQuantityEntity3 = new MaterialQuantityEntity();
                    materialQuantityEntity3.setCategoryId(material.getCategoryId());
                    materialQuantityEntity3.setMaterialId(material.getMaterialId());
                    materialQuantityEntity3.setCode(material.getCode());
                    materialQuantityEntity3.setUnitmeasurement(material.getUnitmeasurement());
                    materialQuantityEntity3.setUnitprice(material.getUnitprice());
                    materialQuantityEntity3.setStorehouseId(material.getStorehouseId());
                    materialQuantityEntity3.setWarehousingquantity(material.getWarehousingquantity());
                    materialQuantityEntity3.setQuantity(material.getWarehousingquantity());
                    materialQuantityEntity3.setTotal(material.getTotal());
                    HttpHeaders headers = new HttpHeaders();
                    headers.add(HttpHeaders.LOCATION, String.valueOf(materialQuantityEntity3.getId()));
                    materialQuantityService.saveMaterialQuantity(materialQuantityEntity3);
                }
            }
        }

        return success(null);
    }

    /**
     * 修改一个 <strong>物资入库与货架关联</strong>
     *
     * @param extId     主键ID
     * @param extEntity 修改后的信息
     */
//    @PutMapping("{id}")
//    public Object update(@PathVariable String id, @RequestBody MaterialwarehousingShelfExtEntity entity) {
//        entity.setId(id);
//        materialwarehousingShelfExtService.updateMaterialwarehousingShelfExt(entity);
//        return new ResponseEntity<>(HttpStatus.OK);
//    }
    @PutMapping("{extId}")
    public Object update(@PathVariable String materialwarehousingId, @PathVariable String
            extId, @RequestBody MaterialwarehousingMaterialExtEntity extEntity) {
        extEntity.setId(extId);
        extEntity.setMaterialwarehousingId(materialwarehousingId);
        materialwarehousingMaterialExtService.updateMaterialwarehousingMaterialExt(extEntity);
        return success(null);
    }

    /**
     * 删除一个 <strong>物资入库与货架关联</strong>
     *
     * @param id 主键ID
     */
    @DeleteMapping("{id}")
    public Object delete(@PathVariable String id) {
        materialwarehousingMaterialExtService.deleteMaterialwarehousingMaterialExt(id);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

    /**
     * 删除多个 <strong>物资入库与货架关联</strong>
     *
     * @param ids 主键ID列表
     */
    @DeleteMapping
    public Object deleteIds(@RequestBody List<String> ids) {
        materialwarehousingMaterialExtService.deleteMaterialwarehousingMaterialExt(ids);
        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
    }

    /**
     * 构建查询条件内容
     *
     * @param entity 实体对象
     * @return lambda query chain wrapper
     */
    private LambdaQueryChainWrapper<MaterialwarehousingMaterialExtEntity> buildLambdaQuery
    (MaterialwarehousingMaterialExtEntity entity) {
        LambdaQueryChainWrapper<MaterialwarehousingMaterialExtEntity> lambdaQuery = materialwarehousingMaterialExtService.lambdaQuery();
        lambdaQuery.eq(StringUtils.isNotBlank(entity.getId()), MaterialwarehousingMaterialExtEntity::getId, entity.getId());
        lambdaQuery.eq(entity.getMaterialwarehousingId() != null, MaterialwarehousingMaterialExtEntity::getMaterialwarehousingId, entity.getMaterialwarehousingId());
        lambdaQuery.eq(entity.getWarehousingquantity() != null, MaterialwarehousingMaterialExtEntity::getWarehousingquantity, entity.getWarehousingquantity());
        lambdaQuery.eq(entity.getTotal() != null, MaterialwarehousingMaterialExtEntity::getTotal, entity.getTotal());
        return lambdaQuery;
    }

    /**
     * 构建查询条件内容
     *
     * @param entity 实体对象
     * @return lambda query chain wrapper
     */
    private QueryWrapper<MaterialwarehousingMaterialExtEntity> buildQuery(MaterialwarehousingMaterialExtEntity
                                                                                  entity) {
        QueryWrapper<MaterialwarehousingMaterialExtEntity> wrapper = new QueryWrapper<>();
        wrapper.eq(StringUtils.isNotBlank(entity.getId()), "id", entity.getId());
        wrapper.eq(entity.getMaterialwarehousingId() != null, "materialwarehousing_id", entity.getMaterialwarehousingId());
        wrapper.eq(entity.getWarehousingquantity() != null, "warehousingquantity", entity.getWarehousingquantity());
        wrapper.eq(entity.getTotal() != null, "total", entity.getTotal());
        return wrapper;
    }

}
